package com.snake.springboot.custom.service.impl.base;

import com.snake.springboot.custom.api.model.base.CustPointsFreezeModel;
import com.snake.springboot.custom.api.model.base.CustPointsModel;
import com.snake.springboot.custom.api.model.common.CommonVal;
import com.snake.springboot.custom.api.model.points.PointsChangeModel;
import com.snake.springboot.custom.api.request.base.CustomReq;
import com.snake.springboot.custom.api.service.base.CustPointsService;
import com.snake.springboot.custom.dao.mybatis.entity.base.CustPointsDO;
import com.snake.springboot.custom.dao.mybatis.entity.base.CustPointsFlowDO;
import com.snake.springboot.custom.dao.mybatis.entity.base.CustPointsFreezeDO;
import com.snake.springboot.custom.dao.mybatis.mappers.base.CustPointsFlowMapper;
import com.snake.springboot.custom.dao.mybatis.mappers.base.CustPointsFreezeMapper;
import com.snake.springboot.custom.dao.mybatis.mappers.base.CustPointsMapper;
import com.snake.springboot.custom.service.assemble.base.CustPointsAssemble;
import com.snake.springboot.custom.service.assemble.base.CustPointsFzAssemble;
import org.snake.common.exception.OperationException;
import org.snake.common.utils.PropertyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CustPointsServiceImpl implements CustPointsService{

    @Autowired
    private CustPointsMapper custPointsMapper;
    @Autowired
    private CustPointsFlowMapper flowMapper;
    @Autowired
    private CustPointsFreezeMapper freezeMapper;

    @Override
    public void addPoints(CustomReq customReq) {
        CustPointsDO custPointsDO = CustPointsAssemble.pointsDO(customReq);
        custPointsMapper.insert(custPointsDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PointsChangeModel model) {
        model.setChangePoints(model.getChangePoints().abs());
        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        //增加算力
        custPointsMapper.add(model.getCustomId(),model.getChangePoints());
        //增加记录
        CustPointsFlowDO flowDO = CustPointsAssemble.addDOAss(model,custPointsDO);
        flowMapper.insert(flowDO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reduce(PointsChangeModel model) {
        model.setChangePoints(model.getChangePoints().abs().negate());
        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        if(custPointsDO.getPoints().compareTo(model.getChangePoints().abs())<0){
            throw new OperationException("算力不足");
        }
        //扣减算力
        custPointsMapper.reduce(model.getCustomId(),model.getChangePoints().abs());
        //扣减记录
        CustPointsFlowDO flowDO = CustPointsAssemble.addDOAss(model,custPointsDO);
        flowMapper.insert(flowDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void expire(PointsChangeModel model) {
        model.setChangePoints(model.getChangePoints().abs().negate());
        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        if(custPointsDO.getPoints().compareTo(model.getChangePoints().abs())<0){
            model.setChangePoints(custPointsDO.getPoints().negate());
        }
        //扣减算力
        custPointsMapper.reduce(model.getCustomId(),model.getChangePoints().abs());
        //扣减记录
        CustPointsFlowDO flowDO = CustPointsAssemble.addDOAss(model,custPointsDO);
        flowMapper.insert(flowDO);
    }

    /**
     * 冻结算力
     * @param model
     */
    @Transactional
    @Override
    public void freeze(CustPointsFreezeModel model) {
        OperationException.checkNotNull(model.getFreezePoints(),"冻结算力不能为空");

        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        if (custPointsDO==null){
            throw new OperationException("算力不存在，请刷新或重新登录！！");
        }

        if(custPointsDO.getPoints().compareTo(model.getFreezePoints().abs())<0){
            throw new OperationException("算力不足预计需要的算力："+model.getFreezePoints());
        }
        //扣减算力+增加冻结数
        custPointsDO.setFreezePoints(model.getFreezePoints());
        custPointsMapper.freeze(custPointsDO);
        //更改冻结记录
        CustPointsFreezeDO freezeDO = CustPointsFzAssemble.freezeDOAss(model,custPointsDO);
        freezeMapper.insertSelective(freezeDO);
    }

    /**
     * 解冻算力
     * @param model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void thaw(CustPointsFreezeModel model) {
        OperationException.checkNotNull(model.getFreezePoints(),"冻结算力不能为空");
        //查询是否解冻过
        CustPointsFreezeDO freezeDO =freezeMapper.queryByFreeze(model.getParentId());
        if(freezeDO==null||freezeDO.getState().equals(CommonVal.Y)){
            return;
        }
        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        custPointsDO.setFreezePoints(freezeDO.getFreezePoints());
        int i = freezeMapper.thawStatus(freezeDO);
        if (i==0){
            return;
        }
        custPointsMapper.thaw(custPointsDO);

    }

    /**
     * 扣减冻结算力
     * @param model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean reduceFreeze(CustPointsFreezeModel model) {
        OperationException.checkNotNull(model.getFreezePoints(),"冻结算力不能为空");
        OperationException.checkNotNull(model.getPoints(),"扣减算力不能为空");
        //查询是否解冻过
        CustPointsFreezeDO freezeDO =freezeMapper.queryByFreeze(model.getParentId());
        if(freezeDO==null||freezeDO.getState().equals(CommonVal.Y)){
            return false;
        }
        //解冻
        int i = freezeMapper.thawStatus(freezeDO);
        if (i==0){
            return false;
        }
        //扣减算力
        CustPointsDO custPointsDO = custPointsMapper.queryByCustomId(model.getCustomId());
        custPointsDO.setFreezePoints(freezeDO.getFreezePoints());
        CustPointsDO reduceFreeze = CustPointsAssemble.addDOAss(model);
        custPointsMapper.reduceFreeze(reduceFreeze);
        //写算力扣减记录
        CustPointsFlowDO flowDO = CustPointsAssemble.addDOAss(model,custPointsDO);
        flowMapper.insert(flowDO);
        return true;
    }

    @Override
    public CustPointsModel queryById(String customId) {
        CustPointsDO pointsDO = custPointsMapper.queryByCustomId(customId);
        CustPointsModel model = new CustPointsModel();
        PropertyUtils.copyProperties(model,pointsDO);
        return model;
    }
}
